﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text;
using System.Threading.Tasks;
using StyleMVVM.DependencyInjection;
using StyleMVVM.Utilities;
#if NETFX_CORE
using Windows.UI.Core;
using Windows.UI.Xaml;
#else
using System.Windows;
using System.Windows.Threading;
#endif

namespace StyleMVVM.View.Impl
{
	public sealed class ViewAwareStatus : IViewAwareStatus
	{
		private List<WeakDelegate> loadedDelegates = new List<WeakDelegate>();
		private List<WeakDelegate> unloadedDelegates = new List<WeakDelegate>(); 
		private WeakReference viewReference;

		public static void RegisterExport(IDependencyInjectionContainer container)
		{
			container.Register(typeof(ViewAwareStatus)).As(typeof(IViewAwareStatus));
		}

		public ViewAwareStatus(IViewContext viewContext)
		{
			if (viewContext == null)
			{
				throw new ArgumentNullException("viewContext");
			}

			object view = viewContext.View;

			if (view == null)
			{
				throw new ArgumentException("View property can't be null", "viewContext");
			}

			viewReference = new WeakReference(view);

			FrameworkElement frameworkElement = view as FrameworkElement;

			if (frameworkElement != null)
			{
				frameworkElement.Loaded += FrameworkElementOnLoaded;
				frameworkElement.Unloaded += FrameworkElementOnUnloaded;

				Dispatcher = frameworkElement.Dispatcher;
			}
		}
		
		public event EventHandler<object> ViewLoaded
		{
			add
			{
				loadedDelegates.Add(new WeakDelegate(value));

#if NETFX_CORE
				return new EventRegistrationToken();
#endif
			}
			remove { }
		}

		public event EventHandler<object> ViewUnloaded
		{
			add
			{
				unloadedDelegates.Add(new WeakDelegate(value));

#if NETFX_CORE
				return new EventRegistrationToken();
#endif
			}
			remove { }
		}

#if DOT_NET
		public event EventHandler<object> ViewActivated;

		public event EventHandler<object> ViewDeactivated;
#endif

#if NETFX_CORE
		public CoreDispatcher Dispatcher { get; private set; }
#else
		public Dispatcher Dispatcher { get; private set; }
#endif

		public object View
		{
			get { return viewReference.Target; }
		}

		private void FrameworkElementOnUnloaded(object sender, RoutedEventArgs routedEventArgs)
		{
			foreach (WeakDelegate unloadedDelegate in unloadedDelegates)
			{
				unloadedDelegate.Invoke(sender, routedEventArgs);
			}
		}

		private void FrameworkElementOnLoaded(object sender, RoutedEventArgs routedEventArgs)
		{
			foreach (WeakDelegate loadedDelegate in loadedDelegates)
			{
				loadedDelegate.Invoke(sender, routedEventArgs);
			}
		}
	}
}
